﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
//using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;


using System.Windows.Controls.Primitives;
using System.Diagnostics.CodeAnalysis;

using ICSharpCode.Core.Presentation;
using ICSharpCode.Core.Services;
using ICSharpCode.Core;

using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Commands ;

using AvalonDock;

using System.IO;

namespace AddInWithPad
{
    /// <summary>
    /// Test.xaml 的交互逻辑
    /// </summary>
    public partial class Test : Window
    {
        public Test()
        {
            InitializeComponent();
        }

        DockingManager dockingManager = new DockingManager();
        List<IWorkbenchWindow> workbenchWindows = new List<IWorkbenchWindow>();

        const string mainMenuPath = "/SharpDevelop/Workbench/MainMenu";
        const string viewContentPath = "/SharpDevelop/Workbench/Pads";
        ToolBar[] toolBars;
        StatusBar statusBar = new StatusBar();
        List<PadDescriptor> padDescriptorCollection = new List<PadDescriptor>();

        public event EventHandler ActiveWorkbenchWindowChanged;
        public event EventHandler ActiveViewContentChanged;
        public event EventHandler ActiveContentChanged;
        public event ViewContentEventHandler ViewOpened;

        IViewContent activeViewContent;

        public Window MainWindow { get { return this; } }

        public IViewContent ActiveViewContent
        {
            get
            {
                WorkbenchSingleton.AssertMainThread();
                return activeViewContent;
            }
            private set
            {
                if (activeViewContent != value)
                {
                    activeViewContent = value;

                    if (ActiveViewContentChanged != null)
                    {
                        ActiveViewContentChanged(this, EventArgs.Empty);
                    }
                }
            }
        }

        object activeContent;

        public object ActiveContent
        {
            get
            {
                WorkbenchSingleton.AssertMainThread();
                return activeContent;
            }
            private set
            {
                if (activeContent != value)
                {
                    activeContent = value;

                    if (ActiveContentChanged != null)
                    {
                        ActiveContentChanged(this, EventArgs.Empty);
                    }
                }
            }
        }

        IWorkbenchWindow activeWorkbenchWindow;

        public IWorkbenchWindow ActiveWorkbenchWindow
        {
            get
            {
                WorkbenchSingleton.AssertMainThread();
                return activeWorkbenchWindow;
            }
            private set
            {
                if (activeWorkbenchWindow != value)
                {
                    if (activeWorkbenchWindow != null)
                    {
                        activeWorkbenchWindow.ActiveViewContentChanged -= WorkbenchWindowActiveViewContentChanged;
                    }

                    activeWorkbenchWindow = value;

                    if (value != null)
                    {
                        value.ActiveViewContentChanged += WorkbenchWindowActiveViewContentChanged;
                    }

                    if (ActiveWorkbenchWindowChanged != null)
                    {
                        ActiveWorkbenchWindowChanged(this, EventArgs.Empty);
                    }
                    WorkbenchWindowActiveViewContentChanged(null, null);
                }
            }
        }


        void WorkbenchWindowActiveViewContentChanged(object sender, EventArgs e)
        {
            if (workbenchLayout != null)
            {
                // update ActiveViewContent
                IWorkbenchWindow window = this.ActiveWorkbenchWindow;
                if (window != null)
                    this.ActiveViewContent = window.ActiveViewContent;
                else
                    this.ActiveViewContent = null;

                // update ActiveContent
                this.ActiveContent = workbenchLayout.ActiveContent;
            }
        }
		

        bool closeAll;
        void OnActiveWindowChanged(object sender, EventArgs e)
        {
            if (closeAll)
                return;

            if (workbenchLayout != null)
            {
                this.ActiveContent = workbenchLayout.ActiveContent;
                this.ActiveWorkbenchWindow = workbenchLayout.ActiveWorkbenchWindow;
            }
            else
            {
                this.ActiveContent = null;
                this.ActiveWorkbenchWindow = null;
            }
        }

        IWorkbenchLayout workbenchLayout;
        public IWorkbenchLayout WorkbenchLayout
        {
            get
            {
                return workbenchLayout;
            }
            set
            {
                WorkbenchSingleton.AssertMainThread();

                if (workbenchLayout != null)
                {
                    workbenchLayout.ActiveContentChanged -= OnActiveWindowChanged;
                    workbenchLayout.Detach();
                }
                if (value != null)
                {
                    //value.Attach(this);
                    value.ActiveContentChanged += OnActiveWindowChanged;
                }
                workbenchLayout = value;
                OnActiveWindowChanged(null, null);
            }
        }
		

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                mainContent.Content = dockingManager;
                StartupSettings startup = new StartupSettings();
                startup.ApplicationRootPath = AppDomain.CurrentDomain.BaseDirectory;
                startup.AllowUserAddIns = true;
                startup.AllowAddInConfigurationAndExternalAddIns = true;

                startup.AddAddInsFromDirectory(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns"));

                CoreStartup coreSt = new CoreStartup("ADDIn Main");
                PropertyService.InitializeService(AppDomain.CurrentDomain.BaseDirectory, "", "Default");

                if (startup.AllowAddInConfigurationAndExternalAddIns)
                {
                    coreSt.ConfigureExternalAddIns(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns.xml"));
                }
                if (startup.AllowUserAddIns)
                {
                    coreSt.ConfigureUserAddIns(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddInInstallTemp"),
                                                System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns"));
                }

                dockingManager.Loaded += new RoutedEventHandler(dockingManager_Loaded);
                coreSt.RunInitialization();
                //LayoutConfiguration.ReloadDefaultLayout();

              
               
                mainMenu.ItemsSource = MenuService.CreateMenuItems(this, this, mainMenuPath, activationMethod: "MainMenu", immediatelyExpandMenuBuildersForShortcuts: true);

                toolBars = ToolBarService.CreateToolBars(this, this, "/SharpDevelop/Workbench/ToolBar");
                if (toolBars != null)
                {
                    foreach (ToolBar tb in toolBars)
                    {
                        DockPanel.SetDock(tb, Dock.Top);
                        dockPanel.Children.Insert(1, tb);
                    }
                    DockPanel.SetDock(statusBar, Dock.Bottom);
                    dockPanel.Children.Insert(dockPanel.Children.Count - 2, statusBar);
                }
                UpdateMenu();
                

            }
            catch (Exception ex)
            {
                
            }
        }

        void dockingManager_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                LayoutConfiguration.LoadLayoutConfiguration();
                LoadConfiguration();
                foreach (PadDescriptor content in AddInTree.BuildItems<PadDescriptor>(viewContentPath, this, false))
                {
                    if (content != null)
                    {
                        ShowPad(content);
                    }
                }			
            }
            catch (Exception ex)
            {

            }
        }


        public void ShowPad(PadDescriptor content)
        {
            WorkbenchSingleton.AssertMainThread();
            if (content == null)
                throw new ArgumentNullException("content");
            if (padDescriptorCollection.Contains(content))
                throw new ArgumentException("Pad is already loaded");

            padDescriptorCollection.Add(content);
           
            if (WorkbenchLayout != null)
            {
                WorkbenchLayout.ShowPad(content);
            }
        }

        void UpdateMenu()
        {
            MenuService.UpdateStatus(mainMenu.ItemsSource);
            foreach (ToolBar tb in toolBars)
            {
                ToolBarService.UpdateStatus(tb.ItemsSource);
            }
        }

        private static void ShapCallSample()
        {
            StartupSettings startup = new StartupSettings();
            startup.ApplicationRootPath = AppDomain.CurrentDomain.BaseDirectory;
            startup.AllowUserAddIns = true;
            startup.AllowAddInConfigurationAndExternalAddIns = true;

            startup.AddAddInsFromDirectory(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns"));


            WorkbenchStartup wbc = new WorkbenchStartup();
            wbc.InitializeWorkbench();
            CoreStartup coreSt = new CoreStartup("ADDIn Main");

            if (startup.AllowAddInConfigurationAndExternalAddIns)
            {
                coreSt.ConfigureExternalAddIns(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns.xml"));
            }
            if (startup.AllowUserAddIns)
            {
                coreSt.ConfigureUserAddIns(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddInInstallTemp"),
                                            System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AddIns"));
            }

            coreSt.RunInitialization();
        }

       [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
		void RunWorkbenchInternal(object settings)
		{
			WorkbenchSettings wbSettings = (WorkbenchSettings)settings;
			
			WorkbenchStartup wbc = new WorkbenchStartup();
			LoggingService.Info("Initializing workbench...");
			wbc.InitializeWorkbench();
			
			RunWorkbenchInitializedCommands();
			
			LoggingService.Info("Starting workbench...");
			Exception exception = null;
			// finally start the workbench.
			try {
                wbc.Run(wbSettings.InitialFileList);
			} finally {
				LoggingService.Info("Unloading services...");
				try {
					WorkbenchSingleton.OnWorkbenchUnloaded();
					PropertyService.Save();
				} catch (Exception ex) {
					LoggingService.Warn("Exception during unloading", ex);
					if (exception == null) {
						exception = ex;
					}
				}
			}
			LoggingService.Info("Finished running workbench.");
		
			if (exception != null) {
				const string errorText = "Unhandled exception terminated the workbench";
				LoggingService.Fatal(exception);
				
			}
		}
		
		void RunWorkbenchInitializedCommands()
		{
			foreach (ICommand command in AddInTree.BuildItems<ICommand>("/Workspace/AutostartAfterWorkbenchInitialized", null, false)) {
				try {
					command.Run();
				} catch (Exception ex) {
					// allow startup to continue if some commands fail
					MessageService.ShowException(ex);
				}
			}
		}

      

        bool Busy = false;
        public void LoadConfiguration()
        {
            //if (!dockingManager.IsLoaded)
            //    return;
            Busy = true;
            try
            {
                TryLoadConfiguration();
            }
            catch (Exception ex)
            {
                MessageService.ShowException(ex);
                // ignore errors loading configuration
            }
            finally
            {
                Busy = false;
            }
            //foreach (AvalonPadContent p in pads.Values)
            //{
            //    p.LoadPadContentIfRequired();
            //}
        }

        void TryLoadConfiguration()
        {
            bool isPlainLayout = LayoutConfiguration.CurrentLayoutName == "Plain";
            if (File.Exists(LayoutConfiguration.CurrentLayoutFileName))
            {
                try
                {
                    LoadLayout(LayoutConfiguration.CurrentLayoutFileName, isPlainLayout);
                    return;
                }
                catch (FileFormatException)
                {
                    // error when version of AvalonDock has changed: ignore and load template instead
                }
            }
            if (File.Exists(LayoutConfiguration.CurrentLayoutTemplateFileName))
            {
                LoadLayout(LayoutConfiguration.CurrentLayoutTemplateFileName, isPlainLayout);
            }
        }

        void LoadLayout(string fileName, bool hideAllLostPads)
        {
            LoggingService.Info("Loading layout file: " + fileName + ", hideAllLostPads=" + hideAllLostPads);
            //			DockableContent[] oldContents = dockingManager.DockableContents;
            dockingManager.RestoreLayout(fileName);
            //			DockableContent[] newContents = dockingManager.DockableContents;
            // Restoring a AvalonDock layout will remove pads that are not
            // stored in the layout file.
            // We'll re-add those lost pads.
            //			foreach (DockableContent lostContent in oldContents.Except(newContents)) {
            //				AvalonPadContent padContent = lostContent as AvalonPadContent;
            //				LoggingService.Debug("Re-add lost pad: " + padContent);
            //				if (padContent != null && !hideAllLostPads) {
            //					padContent.ShowInDefaultPosition();
            //				} else {
            //					dockingManager.Hide(lostContent);
            //				}
            //			}
        }

    }
}
